<?php

declare(strict_types=1);

namespace App\Repositories\Gashapon;

use AlibabaCloud\Smartag\V20180313\ModifyQos;
use App\Models\MainDB\Gashapon\PoolPrize as Model;
use App\Traits\Singleton;
use Illuminate\Support\Facades\DB;

class PoolPrizeRepository
{
    use Singleton;

    public function createNextRounPrizes(int $poolId, array $map)
    {
        Model::query()->where(['pool_id' => $poolId])->update(['total_count' => 0]); // 清空本轮礼物总数
        $this->appendPrizes($poolId, $map);                                          // 追加礼物当前数量
        return $this->one(['pool_id' => $poolId]);
    }

    /**
     * 填充奖品
     *
     * @param int   $poolId
     * @param array $map [ [prize_id => prize_count] ]
     */
    public function appendPrizes(int $poolId, array $map)
    {
        $insert = [];
        $update = [];
        $pool   = Model::query()->where(['pool_id' => $poolId])->get();
        foreach ($map as $prizeId => $prizeCount) {
            $prize = $pool->where('prize_id', $prizeId)->first();
            if ($prize) { // 奖励存在
                $update[$prizeId] = $prizeCount;
            } else { // 奖励不存在
                $insert[] = ['pool_id' => $poolId, 'prize_id' => $prizeId, 'count' => $prizeCount, 'total_count' => $prizeCount];
            }
        }
        if ($insert) {
            Model::query()->insert($insert);
        }
        if ($update) {
            $this->batchIncPrizesByPoolId($poolId, $update);
        }
    }

    // 批量增加礼物数量（抽完补奖池, 额外设置总数）
    public function batchIncPrizesByPoolId(int $poolId, array $update)
    {
        if (empty($update)) {
            return true;
        }

        $prizeIds      = array_keys($update);
        $prizeIdsSting = implode(',', $prizeIds);

        $model = new Model();
        $table = $model->getTable();
        $sql   = "update {$table} set ";
        // 增加数量
        $sql .= "`count` = case `prize_id`";
        foreach ($update as $prizeId => $prizeCount) {
            $sql .= "when {$prizeId} then `count` + {$prizeCount} ";
        }
        $sql .= "else `count` end, ";
        // 增加总数
        $sql .= "`total_count` = case `prize_id` ";
        foreach ($update as $prizeId => $prizeCount) {
            $sql .= "when {$prizeId} then `total_count` + {$prizeCount} ";
        }
        $sql .= "else `total_count` end ";
        // 条件
        $sql .= " where pool_id = '{$poolId}' and prize_id in ($prizeIdsSting)";

        return DB::update($sql);
    }

    // 批量减少礼物数量
    public function batchDecPrizesByPoolId(int $poolId, array $update)
    {
        if (empty($update)) {
            return true;
        }

        $model = new Model();
        $table = $model->getTable();
        $sql   = "update {$table} set  `count` = case `prize_id`";
        foreach ($update as $prizeId => $prizeCount) {
            $sql .= "when {$prizeId} then `count` - {$prizeCount} ";
        }
        $sql .= "else `count` end where pool_id = '{$poolId}'";

        return DB::update($sql);
    }

    public function getPoolPrize(int $poolId)
    {
        $query = Model::query();
        $query->where(['pool_id' => $poolId]);
        $query->with(['prize']);
        $models = $query->get();
        $models->transform(function ($item) {
            $item->price = $item->prize->price;
            $item->name  = $item->prize->name;
            // return $item->only(['prize_id', 'count', 'price', 'name']);
            return $item;
        });
        return $models;
    }

    public function all(array $filters = [], int $page = 1, int $perPage = 15)
    {
        $query = Model::query();
        $query->where($filters);
        $models = $query->paginate($perPage, ['*'], 'page', $page);
        return $models;
    }

    public function one(array $filters, bool $fail = false)
    {
        $query = Model::query();
        $query->where($filters);
        $model = $fail ? $query->firstOrFail() : $query->first();
        return $model;
    }

    public function find(int $id)
    {
        $model = $this->one(['id' => $id], true);
        return $model;
    }

    public function create(array $data)
    {
        $model = new Model();
        $model->fill($data);
        $model->save();
        $model->refresh();

        return $model;
    }

    public function update(int $id, array $data)
    {
        $model = $this->find($id);
        $model->fill($data);
        $model->save();
        return $model;
    }
}
